﻿using Newtonsoft.Json;
using Plugin.GrabImage.Views;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using VisionDesigner;
using VM.CameraSet;
using VM.Common.Enums;
using VM.Common.Helper;
using VM.Core;
using VM.Start.Attributes;
using VM.Start.Common.Hik;
using VM.Start.Common.Provide;
using VM.Start.Core;
using VM.Start.Models;
using VM.Start.Services;

namespace Plugin.GrabImage.ViewModels
{

    #region enum
    public enum PixelFormat
    {
        RGB24,
        MONO8
    }

    #endregion

    [Category("常用工具")]
    [DisplayName("采集图像")]
    [ModuleImageName("GrabImage")]
    [JsonObject(MemberSerialization.OptOut)]
    public class GrabImageViewModel : ModuleBase
    {
        #region  属性

        public uint Width;
        public uint Height;
        public MVD_PIXEL_FORMAT PIXEL_FORMAT = MVD_PIXEL_FORMAT.MVD_PIXEL_NULL;
        public MVD_IMAGE_DATA_INFO ImageData = null;
        [Newtonsoft.Json.JsonIgnore]
        private CMvdImage _DispImage;
        [Newtonsoft.Json.JsonIgnore]
        public CMvdImage DispImage
        {
            get
            {
                if ((_DispImage == null || _DispImage.IsEmpty) &&
                    ImageData != null && ImageData.stDataChannel[0].arrDataBytes != null &&
                    Width != 0 && Height != 0 && PIXEL_FORMAT != MVD_PIXEL_FORMAT.MVD_PIXEL_NULL)
                {
                    _DispImage = new CMvdImage();
                    _DispImage.InitImage(Width, Height, PIXEL_FORMAT, ImageData);
                }
                return _DispImage;
            }
            set
            {
                _DispImage = value;
                if (_DispImage != null && !_DispImage.IsEmpty)
                {
                    Width = _DispImage.Width;
                    Height = _DispImage.Height;
                    PIXEL_FORMAT = _DispImage.PixelFormat;
                    ImageData = _DispImage.GetImageData();
                }
                else
                {
                    Width = 0;
                    Height = 0;
                    PIXEL_FORMAT = MVD_PIXEL_FORMAT.MVD_PIXEL_NULL;
                    ImageData = null;
                }
            }
        }


        /// <summary>
        /// 内容标题
        /// </summary>
        private string _ContentHeader = "文件目录";
        public string ContentHeader
        {
            get { return _ContentHeader; }
            set { _ContentHeader = value; RaisePropertyChanged(); }
        }

        /// <summary>
        /// 指定图像
        /// </summary>
        private eImageSource _ImageSource = eImageSource.指定图像;
        public eImageSource ImageSource
        {
            get { return _ImageSource; }
            set
            {
                Set(ref _ImageSource, value, new Action(() =>
                {
                    switch (_ImageSource)
                    {
                        case eImageSource.指定图像:
                            ContentHeader = "指定图像";
                            break;
                        case eImageSource.文件目录:
                            ContentHeader = "文件目录";
                            break;
                        case eImageSource.相机采集:
                            ContentHeader = "相机采集";
                            break;
                        default:
                            break;
                    }
                }));
            }
        }

        /// <summary>
        /// 图片路径
        /// </summary>
        private string _ImagePath;
        public string ImagePath
        {
            get { return _ImagePath; }
            set
            {
                _ImagePath = value;
                RaisePropertyChanged();
            }
        }

        /// <summary>
        /// 循环读取
        /// </summary>
        private bool _IsCyclicRead = true;
        public bool IsCyclicRead
        {
            get { return _IsCyclicRead; }
            set
            {
                Set(ref _IsCyclicRead, value);
            }
        }

        /// <summary>
        /// 图片文件夹路径
        /// </summary>
        private string _FilePath;
        public string FilePath
        {
            get { return _FilePath; }
            set { _FilePath = value; RaisePropertyChanged(); }
        }

        public ObservableCollection<ImageNameModel> ImageNameModels { get; set; } = new ObservableCollection<ImageNameModel>();

        /// <summary>图像索引</summary>
        public int _SelectedIndex = 0;
        public int SelectedIndex
        {
            get { return _SelectedIndex; }
            set
            {
                Set(ref _SelectedIndex, value);
                LoadImageByIndex(value);
            }
        }
        #endregion
        #region 数据接口
        /// <summary>相机列表</summary>
        [Newtonsoft.Json.JsonIgnore]
        public ObservableCollection<CameraBase> CameraModels
        {
            get => CameraSetViewModel.Ins.CameraModels;
            set { RaisePropertyChanged(nameof(CameraModels)); }
        }
        [Newtonsoft.Json.JsonIgnore]
        private CameraBase _SelectedCameraModel;
        [Newtonsoft.Json.JsonIgnore]
        public CameraBase SelectedCameraModel
        {
            get
            {
                if (_SelectedCameraModel == null && CameraModels.Count > 0)
                {
                    _SelectedCameraModel = CameraModels.FirstOrDefault();
                }
                return _SelectedCameraModel;
            }
            set => Set(ref _SelectedCameraModel, value);
        }

        [Newtonsoft.Json.JsonIgnore]
        public Array AcquisitionModes
        {
            get { return Enum.GetValues(typeof(eTrigMode)); }
            set {; }
        }

        /// <summary>
        /// 当前采集模式
        /// </summary>
        [Newtonsoft.Json.JsonIgnore]
        private eTrigMode _AcquisitionMode = eTrigMode.软触发;
        [Newtonsoft.Json.JsonIgnore]
        public eTrigMode AcquisitionMode
        {
            get { return _AcquisitionMode; }
            set
            {
                Set(ref _AcquisitionMode, value, new Action(() =>
                {
                }));
            }
        }

        /// <summary>
        /// 曝光时间
        /// </summary>
        [Newtonsoft.Json.JsonIgnore]
        private LinkVarModel _ExposureTime = new LinkVarModel() { Text = "20000" };
        [Newtonsoft.Json.JsonIgnore]
        public LinkVarModel ExposureTime
        {
            get { return _ExposureTime; }
            set { _ExposureTime = value; RaisePropertyChanged(); }
        }

        /// <summary>
        /// 增益
        /// </summary>
        [Newtonsoft.Json.JsonIgnore]
        private LinkVarModel _Gain = new LinkVarModel() { Text = "5" };
        [Newtonsoft.Json.JsonIgnore]
        public LinkVarModel Gain
        {
            get { return _Gain; }
            set { _Gain = value; RaisePropertyChanged(); }
        }

        private Array _PixelFormatArray = Enum.GetValues(typeof(PixelFormat));
        public Array PixelFormatArray
        {
            get { return _PixelFormatArray; }
            set { Set(ref _PixelFormatArray, value); }
        }

        [Newtonsoft.Json.JsonIgnore]
        private PixelFormat _PixelFormatType = PixelFormat.RGB24;
        [Newtonsoft.Json.JsonIgnore]
        public PixelFormat PixelFormatType
        {
            get { return _PixelFormatType; }
            set
            {
                Set(ref _PixelFormatType, value);
                switch (ImageSource)
                {
                    case eImageSource.指定图像:
                        if (!File.Exists(ImagePath))
                        {
                            DispImage = null;
                            break;
                        }
                        RImage rImage = new RImage();
                        rImage.LoadImagePath(ImagePath);
                        DispImage = rImage;
                        if (PixelFormatType == PixelFormat.MONO8 && !DispImage.IsEmpty)
                        {
                            DispImage.ConvertImagePixelFormat(MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08);
                        }
                        System.Windows.Application.Current.Dispatcher.Invoke(() =>
                        {
                            mWindowH.Image = DispImage;
                        });
                        break;
                    case eImageSource.文件目录:
                        if (ImageNameModels == null || ImageNameModels.Count == 0)
                        {
                            break;
                        }
                        System.Windows.Application.Current.Dispatcher.Invoke(() =>
                        {
                            if (File.Exists(ImageNameModels[SelectedIndex].ImagePath))
                            {
                                RImage rImage = new RImage();
                                rImage.LoadImagePath(ImageNameModels[SelectedIndex].ImagePath);
                                DispImage = rImage;
                                if (PixelFormatType == PixelFormat.MONO8 && !DispImage.IsEmpty)
                                {
                                    DispImage.ConvertImagePixelFormat(MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08);
                                }
                                mWindowH.Image = DispImage;
                            }
                        });
                        break;
                    case eImageSource.相机采集:
                        if (SelectedCameraModel.Image != null && !SelectedCameraModel.Image.IsEmpty)
                        {
                            System.Windows.Application.Current.Dispatcher.Invoke(() =>
                            {
                                DispImage = SelectedCameraModel.Image.Clone();
                                if (PixelFormatType == PixelFormat.MONO8 && !DispImage.IsEmpty)
                                {
                                    DispImage.ConvertImagePixelFormat(MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08);
                                }
                                mWindowH.Image = DispImage;
                            });
                        }
                        break;
                    default:
                        break;
                }
                GC.Collect();
            }
        }

        #endregion
        #region  指令
        [Newtonsoft.Json.JsonIgnore]
        private CommandBase _ImagePathCommand;
        [Newtonsoft.Json.JsonIgnore]
        public CommandBase ImagePathCommand
        {
            get
            {
                if (_ImagePathCommand == null)
                {
                    _ImagePathCommand = new CommandBase((obj) =>
                    {
                        Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
                        dlg.Filter = "所有图像文件 | *.bmp; *.pcx; *.png; *.jpg; *.gif;*.tif; *.ico; *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf";
                        if (dlg.ShowDialog() == true)
                        {
                            ImagePath = dlg.FileName;
                            ExeModule();
                        }
                    });
                }
                return _ImagePathCommand;
            }
        }
        /// <summary>
        /// 确定指令
        /// </summary>
        //[NonSerialized]
        [Newtonsoft.Json.JsonIgnore]
        private CommandBase _ConfirmCommand;
        [Newtonsoft.Json.JsonIgnore]
        public CommandBase ConfirmCommand
        {
            get
            {
                if (_ConfirmCommand == null)
                {
                    _ConfirmCommand = new CommandBase((obj) =>
                    {
                        var view = this.ModuleView as GrabImageView;
                        if (view != null)
                        {
                            view.Close();
                        }
                    });
                }
                return _ConfirmCommand;
            }
        }

        [Newtonsoft.Json.JsonIgnore]
        private CommandBase _FilePathCommand;
        [Newtonsoft.Json.JsonIgnore]
        public CommandBase FilePathCommand
        {
            get
            {
                if (_FilePathCommand == null)
                {
                    _FilePathCommand = new CommandBase((obj) =>
                    {
                        FolderBrowserDialog folderDialog = new FolderBrowserDialog();
                        if (folderDialog.ShowDialog() == DialogResult.OK)
                        {
                            FilePath = folderDialog.SelectedPath;
                            var files = Directory.GetFiles(FilePath, "*.*", SearchOption.AllDirectories)
                                                .Where(s => new[] { ".jpg", ".gif", ".png", ".bmp", ".eps", ".tif" }.Contains(Path.GetExtension(s).ToLower()));

                            if (files.Any())
                            {
                                var names = files.ToList();
                                // 自然序数排序读取文件夹中图片
                                names.Sort((a, b) =>
                                {
                                    string fileNameA = Path.GetFileNameWithoutExtension(a);
                                    string fileNameB = Path.GetFileNameWithoutExtension(b);
                                    if (int.TryParse(fileNameA, out int numA) && int.TryParse(fileNameB, out int numB))
                                    {
                                        return numA.CompareTo(numB);
                                    }
                                    // 如果文件名不包含数字，则按字符串顺序排序
                                    return fileNameA.CompareTo(fileNameB);
                                });
                                ImageNameModels.Clear();
                                foreach (var name in names)
                                {
                                    ImageNameModels.Add(new ImageNameModel() { ID = ImageNameModels.Count + 1, ImagePath = name, ImageName = Path.GetFileName(name), IsSelected = true });
                                }

                                RImage rImage = new RImage();
                                if (ImageNameModels != null && ImageNameModels.Count > 0 && File.Exists(ImageNameModels[0].ImagePath))
                                {
                                    SelectedIndex = 0;
                                    rImage.LoadImagePath(ImageNameModels[0].ImagePath);
                                    DispImage = rImage;
                                    if (DispImage != null && !DispImage.IsEmpty)
                                    {
                                        var view = ModuleView as GrabImageView;
                                        if (view == null) return;
                                        mWindowH.Image = DispImage;
                                        ChangeModuleRunStatus(eRunStatus.OK);
                                    }
                                    else
                                    {
                                        ChangeModuleRunStatus(eRunStatus.NG);
                                    }
                                }
                                else
                                {
                                    ChangeModuleRunStatus(eRunStatus.NG);
                                }
                            }
                        }
                    });
                }
                return _FilePathCommand;
            }
        }

        [Newtonsoft.Json.JsonIgnore]
        private CommandBase _ExecuteCommand;
        [Newtonsoft.Json.JsonIgnore]
        public CommandBase ExecuteCommand
        {
            get
            {
                if (_ExecuteCommand == null)
                {
                    _ExecuteCommand = new CommandBase((obj) =>
                    {
                        ExeModule();
                    });
                }
                return _ExecuteCommand;
            }
        }

        [Newtonsoft.Json.JsonIgnore]
        private CommandBase _PreviewMouseDoubleClick_FilePath;
        [Newtonsoft.Json.JsonIgnore]
        public CommandBase PreviewMouseDoubleClick_FilePath
        {
            get
            {
                if (_PreviewMouseDoubleClick_FilePath == null)
                {
                    _PreviewMouseDoubleClick_FilePath = new CommandBase((obj) =>
                    {
                        RImage rImage = new RImage();
                        if (File.Exists(ImageNameModels[SelectedIndex].ImagePath))
                        {
                            rImage.LoadImagePath(ImageNameModels[SelectedIndex].ImagePath);
                            DispImage = rImage;
                            if (DispImage != null)
                            {
                                var view = ModuleView as GrabImageView;
                                if (view == null) return;
                                mWindowH.Image = DispImage;
                            }
                        }
                    });
                }
                return _PreviewMouseDoubleClick_FilePath;
            }
        }

        #endregion
        #region 方法
        public override void Loaded()
        {
            base.Loaded();
            var view = ModuleView as GrabImageView;
            if (view != null)
            {
                if (DispImage != null && !DispImage.IsEmpty)
                {
                    mWindowH.Image = DispImage;
                }
                CameraModels = CameraSetViewModel.Ins.CameraModels;
            }
        }

        public override bool ExeModule()
        {
            Stopwatch.Restart();
            try
            {
                switch (ImageSource)
                {
                    case eImageSource.指定图像:
                        HandleSpecifiedImageSource();
                        break;
                    case eImageSource.文件目录:
                        HandleFileDirectorySource();
                        break;
                    case eImageSource.相机采集:
                        HandleCameraCaptureSource();
                        break;
                    default:
                        Logger.AddLog($"未知的图像来源: {ImageSource}", eMsgType.Warn);
                        break;
                }
                if (DispImage != null && !DispImage.IsEmpty)
                {
                    ChangeModuleRunStatus(eRunStatus.OK);
                    return true;
                }
                else
                {
                    Logger.AddLog($"流程[{Solution.Ins.GetProjectById(ModuleParam.ProjectID).ProjectInfo.ProcessName}]执行[{ModuleParam.ModuleName}]模块失败，采集图像为空！", eMsgType.Warn);
                    ChangeModuleRunStatus(eRunStatus.NG);
                    return false;
                }
            }
            catch (Exception ex)
            {
                ChangeModuleRunStatus(eRunStatus.NG);
                Logger.GetExceptionMsg(ex);
                return false;
            }
            finally
            {
                GC.Collect();
            }
        }

        public override bool ExeModule(string TemplateName)
        {
            return ExeModule();
        }

        public override void AddOutputParams()
        {
            base.AddOutputParams();
            AddOutputParam("图像", "Image", DispImage);
        }


        private void LoadImageByIndex(int index)
        {
            if (index >= 0 && index < ImageNameModels.Count)
            {
                var imagePath = ImageNameModels[index].ImagePath;
                if (File.Exists(imagePath))
                {
                    var image = LoadAndConvertImage(imagePath);
                    DispImage = image;
                    UpdateDisplayImage();
                }
            }
        }

        private RImage LoadAndConvertImage(string imagePath)
        {
            var rImage = new RImage();
            rImage.LoadImagePath(imagePath);

            if (PixelFormatType == PixelFormat.MONO8 && !rImage.IsEmpty)
            {
                rImage.ConvertImagePixelFormat(MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08);
            }

            return rImage;
        }

        private void UpdateDisplayImage()
        {
            System.Windows.Application.Current.Dispatcher.Invoke(() =>
            {
                mWindowH.Image = DispImage;
            });
        }

        private void HandleSpecifiedImageSource()
        {
            if (!File.Exists(ImagePath))
            {
                DispImage = null;
                return;
            }

            DispImage = LoadAndConvertImage(ImagePath);
            UpdateDisplayImage();
        }

        private void HandleFileDirectorySource()
        {
            if (ImageNameModels == null || ImageNameModels.Count == 0)
                return;

            System.Windows.Application.Current.Dispatcher.Invoke(() =>
            {
                SelectedIndex = IsCyclicRead
                    ? (SelectedIndex >= ImageNameModels.Count - 1 ? 0 : SelectedIndex + 1)
                    : SelectedIndex;
            });
        }

        private void HandleCameraCaptureSource()
        {
            if (SelectedCameraModel == null || !SelectedCameraModel.Connected)
            {
                Logger.AddLog($"{ModuleParam.ModuleName}: 相机未连接!", eMsgType.Warn);
                DispImage = null;
                ChangeModuleRunStatus(eRunStatus.NG);
                UpdateDisplayImage();
                return;
            }

            CameraSetViewModel.Ins.ButtonOperateCommand.Execute("SingleAcq");

            if (SelectedCameraModel.Image != null && !SelectedCameraModel.Image.IsEmpty)
            {
                DispImage = SelectedCameraModel.Image.Clone();
                if (PixelFormatType == PixelFormat.MONO8 && !DispImage.IsEmpty)
                {
                    DispImage.ConvertImagePixelFormat(MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08);
                }
                UpdateDisplayImage();
                ChangeModuleRunStatus(eRunStatus.OK);
            }
            else
            {
                DispImage = null;
                Logger.AddLog("相机采集失败，图像为空", eMsgType.Warn);
                ChangeModuleRunStatus(eRunStatus.NG);
            }
            UpdateDisplayImage();
        }

        #endregion

    }
}
